package com.luke.dt.stock.service;

import com.alibaba.fastjson.JSONObject;
import com.luke.dt.commons.entitys.shared.TblDtMSG;
import com.luke.dt.commons.entitys.stock.TblStock;
import com.luke.dt.commons.entitys.user.TblUser;
import com.luke.dt.commons.enums.BusinessValEnums;
import com.luke.dt.commons.enums.ErrorCodeEnums;
import com.luke.dt.commons.exception.ServiceException;
import com.luke.dt.commons.input.stock.BuyGoodsReqDto;
import com.luke.dt.commons.input.user.FindUserReq;
import com.luke.dt.commons.inter.user.UserInterController;
import com.luke.dt.commons.output.Result;
import com.luke.dt.stock.dao.TblDtMsgMapper;
import com.luke.dt.stock.dao.TblStockMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;

@Slf4j
@Service
@Transactional(readOnly = true)
public class StockServiceImpl implements StockService{

    @Resource
    private TblStockMapper tblStockMapper;

    //@Resource
    @Autowired(required = false)
    private UserInterController userInterController;

    @Resource
    private TblDtMsgMapper tblDtMsgMapper;

    @Override
    public TblStock findStock(String merchan) throws ServiceException {
        TblStock paramStock = new TblStock();
        paramStock.setMerchanName(merchan);
        TblStock dbStock = tblStockMapper.selectOne(paramStock);
        return dbStock;
    }

    @Transactional(readOnly = false)
    @Override
    public Result buyGoods(BuyGoodsReqDto buyGoodsReqDto) throws ServiceException {
        //查询库存
        TblStock paramStock = new TblStock();
        paramStock.setMerchanName(buyGoodsReqDto.getMerchanName());
        TblStock dbStock = tblStockMapper.selectOne(paramStock);

        //超过库存数量
        if(buyGoodsReqDto.getCount() > dbStock.getStock()){
            throw new ServiceException(ErrorCodeEnums.ERROR_CODE_STOCK_NOT_ENOUGH.getCode(),
                    ErrorCodeEnums.ERROR_CODE_STOCK_NOT_ENOUGH.getMessage());
        }

        //调用用户服务，获取用户信息
        FindUserReq findUserReq = new FindUserReq();
        findUserReq.setName(buyGoodsReqDto.getName());
        Result userResult = userInterController.findUser(findUserReq);
        if(userResult == null){//调用失败
            throw new ServiceException(ErrorCodeEnums.ERROR_CODE_SERVICE_CALL_ERROR_USER.getCode(),
                    ErrorCodeEnums.ERROR_CODE_SERVICE_CALL_ERROR_USER.getMessage());
        }
        if(userResult.getCode() != ErrorCodeEnums.ERROR_CODE_SUCCESS.getCode()){//用户服务发生错误
            throw new ServiceException(userResult.getCode(),
                    userResult.getMessage());
        }
        Object userObj = userResult.getData();
        if(userObj == null){//用户不存在
            throw new ServiceException(ErrorCodeEnums.ERROR_CODE_SERVICE_NOT_FIND_USER.getCode(),
                    ErrorCodeEnums.ERROR_CODE_SERVICE_NOT_FIND_USER.getMessage());
        }

        //LinkedHashMap转对象
        TblUser dbUser = linkedHashMapToTblUser(userObj);

        //计算订单总金额
        float totalAmount = dbStock.getMerchanPrice()*buyGoodsReqDto.getCount();
        if(totalAmount > dbUser.getBalance()){//用户余额不足
            throw new ServiceException(ErrorCodeEnums.ERROR_CODE_USER_BALANCE_NOT_ENOUGH.getCode(),
                    ErrorCodeEnums.ERROR_CODE_USER_BALANCE_NOT_ENOUGH.getMessage());
        }

        //（1）先扣减库存
        int updateStockResult = tblStockMapper.updateStock(dbStock.getId(),buyGoodsReqDto.getCount());
        if(updateStockResult != 1){
            throw new ServiceException(ErrorCodeEnums.ERROR_CODE_STOCK_REDU_FAIL.getCode(),
                    ErrorCodeEnums.ERROR_CODE_STOCK_REDU_FAIL.getMessage());
        }

        //（2）再扣减用户钱（插入分布式事物发送端消息表）
        TblDtMSG reduUserDtMSG = new TblDtMSG();
        reduUserDtMSG.setName("扣减用户余额");
        reduUserDtMSG.setBusinessVal(BusinessValEnums.BUSINESS_VAL_REDU_USER_BALANCE.getCode());
        reduUserDtMSG.setCreateTime(new Date());
        //发送给消息队列的消息

        TblUser reduUserData = new TblUser();
        reduUserData.setId(dbUser.getId());
        reduUserData.setBalance(totalAmount);//扣减的金额
        reduUserDtMSG.setData(JSONObject.toJSONString(reduUserData));
        reduUserDtMSG.setRetryNum(0);
        reduUserDtMSG.setStatusVal(1);//预发送
        reduUserDtMSG.setQueueVal("dt_queue_user");//发送到用户服务队列
        tblDtMsgMapper.insertSelective(reduUserDtMSG);
        //（3）最后生成订单（插入分布式事物发送端消息表）

        return new Result(ErrorCodeEnums.ERROR_CODE_SUCCESS.getCode(),
                ErrorCodeEnums.ERROR_CODE_SUCCESS.getMessage());
    }

    /**
     * linkedHashMapToTblUser
     * @param userObj
     * @return
     * @throws ServiceException
     */
    public TblUser linkedHashMapToTblUser(Object userObj) throws ServiceException{
        LinkedHashMap<String,Object> userObjMap = (LinkedHashMap<String,Object>)userObj;
        TblUser dbUser = new TblUser();
        dbUser.setId(((Integer)userObjMap.get("id")).longValue());
        dbUser.setName((String)userObjMap.get("name"));
        dbUser.setBalance(((Double) userObjMap.get("balance")).floatValue());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if(userObjMap.get("createTime") != null){
            try {
                dbUser.setCreateTime(sdf.parse((String)userObjMap.get("createTime")));
            } catch (ParseException e) {
                throw new ServiceException(ErrorCodeEnums.ERROR_CODE_ERROR_SERVER.getCode(),
                        ErrorCodeEnums.ERROR_CODE_ERROR_SERVER.getMessage());
            }
        }
        if(userObjMap.get("updateTime") != null){
            try {
                dbUser.setUpdateTime(sdf.parse((String)userObjMap.get("updateTime")));
            } catch (ParseException e) {
                throw new ServiceException(ErrorCodeEnums.ERROR_CODE_ERROR_SERVER.getCode(),
                        ErrorCodeEnums.ERROR_CODE_ERROR_SERVER.getMessage());
            }
        }
        return dbUser;
    }

}
